package com.unionpay.db;

import java.io.File;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

/**
 * 生成配置文件
 * 
 * @author liuzy
 * @since 2016年5月2日
 */
public class MybatiesConfig {
	private Properties p;
	private String entityPackage;
	private String mapperPackage;
	private String mappingXml;
	private StringBuilder xml;
	public MybatiesConfig(Properties p) {
		this.p = p;
		this.entityPackage = p.getProperty("entityPackage");
		this.mapperPackage = p.getProperty("mapperPackage");
		this.mappingXml = p.getProperty("mappingXml");
	}
	public List<Class<?>> getMappers() throws ClassNotFoundException {
		List<Class<?>> mappers = new ArrayList<Class<?>>();
		for (File file : scanDir(mapperPackage, ".class")) {
			String className = file.getName().substring(0, file.getName().length() - 6);
			Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(mapperPackage + '.' + className);
			mappers.add(clazz);
		}
		return mappers;
	}
	public String buildXml() {
		xml = new StringBuilder();
		addRoot();
		addTypeAliases();

		xml.append("  <environments default=\"work\">\n");
		xml.append("    <environment id=\"work\">\n");
		xml.append("    <transactionManager type=\"JDBC\" />\n");
		xml.append("      <dataSource type=\"POOLED\">\n");
		xml.append("        <property name=\"driver\" value=\"" + p.getProperty("driver") + "\" />\n");
		xml.append("        <property name=\"url\" value=\"" + p.getProperty("url") + "\" />\n");
		xml.append("        <property name=\"username\" value=\"" + p.getProperty("username") + "\" />\n");
		xml.append("        <property name=\"password\" value=\"" + p.getProperty("password") + "\" />\n");
		xml.append("      </dataSource>\n");
		xml.append("    </environment>\n");
		xml.append("  </environments>\n");

		addMappers();
		addEnd();
		return xml.toString();
	}
	public String buildXml(String dataSourceFactoryClassName) {
		xml = new StringBuilder();
		addRoot();
		addTypeAliases();

		xml.append("  <environments default=\"work\">\n");
		xml.append("    <environment id=\"work\">\n");
		xml.append("    <transactionManager type=\"JDBC\" />\n");
		xml.append("      <dataSource type=\"" + dataSourceFactoryClassName + "\">\n");
		xml.append("        <property name=\"driverClass\" value=\"" + p.getProperty("driver") + "\" />\n");
		xml.append("        <property name=\"url\" value=\"" + p.getProperty("url") + "\" />\n");
		xml.append("        <property name=\"username\" value=\"" + p.getProperty("username") + "\" />\n");
		xml.append("        <property name=\"password\" value=\"" + p.getProperty("password") + "\" />\n");
		xml.append("        <property name=\"initialSize\" value=\"" + p.getProperty("initialSize") + "\" />\n");
		xml.append("        <property name=\"maxActive\" value=\"" + p.getProperty("maxActive") + "\" />\n");
		xml.append("        <property name=\"maxWait\" value=\"" + p.getProperty("maxWait") + "\" />\n");
		xml.append("        <property name=\"timeBetweenEvictionRunsMillis\" value=\"" + p.getProperty("timeBetweenEvictionRunsMillis") + "\" />\n");
		xml.append("        <property name=\"minEvictableIdleTimeMillis\" value=\"" + p.getProperty("minEvictableIdleTimeMillis") + "\" />\n");
		xml.append("        <property name=\"filters\" value=\"" + p.getProperty("filters") + "\" />\n");
		xml.append("        <property name=\"validationQuery\" value=\"" + p.getProperty("validationQuery") + "\" />\n");
		xml.append("        <property name=\"testWhileIdle\" value=\"" + p.getProperty("testWhileIdle") + "\" />\n");
		xml.append("        <property name=\"testOnBorrow\" value=\"" + p.getProperty("testOnBorrow") + "\" />\n");
		xml.append("        <property name=\"testOnReturn\" value=\"" + p.getProperty("testOnReturn") + "\" />\n");
		xml.append("      </dataSource>\n");
		xml.append("    </environment>\n");
		xml.append("  </environments>\n");

		addMappers();
		addEnd();
		return xml.toString();
	}
	void addRoot() {
		xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
		xml.append("<!DOCTYPE configuration PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n");
		xml.append("<configuration>\n");
	}
	void addTypeAliases() {
		xml.append("  <typeAliases>\n");
		for (File file : scanDir(entityPackage, ".class")) {
			String name = file.getName().substring(0, file.getName().length() - 6);
			xml.append("    <typeAlias type=\"" + entityPackage + "." + name + "\" alias=\"" + name + "\" />\n");
		}
//		xml.append("    <package name=\"" + entityPackage + "\" />\n");
		xml.append("  </typeAliases>\n");
	}
	void addMappers() {
		xml.append("  <mappers>\n");
		for (File file : scanDir(mapperPackage, ".xml")) {
			xml.append("    <mapper resource=\"" + mapperPackage.replaceAll("\\.", "/") + "/" + file.getName() + "\" />\n");
		}
//		xml.append("    <package name=\"" + mappingXml + "\" />\n");
		xml.append("  </mappers>\n");
	}
	void addEnd() {
		xml.append("</configuration>");
	}
	public List<File> scanDir(String packageName, String suffix) {
		List<File> files = new ArrayList<File>();
		try {
			String packageDirName = packageName.replace('.', '/');
			Enumeration<URL> dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
			while (dirs.hasMoreElements()) {
				URL url = dirs.nextElement();
				String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
				File dir = new File(filePath);
				if (!dir.exists() || !dir.isDirectory()) {
					return files;
				}
				for (File file : dir.listFiles()) {
					if (file.getPath().endsWith(suffix)) {
						files.add(file);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return files;
	}
	public String getEntityPackage() {
		return entityPackage;
	}
	public void setEntityPackage(String entityPackage) {
		this.entityPackage = entityPackage;
	}
	public String getMapperPackage() {
		return mapperPackage;
	}
	public void setMapperPackage(String mapperPackage) {
		this.mapperPackage = mapperPackage;
	}
	public String getMappingXml() {
		return mappingXml;
	}
	public void setMappingXml(String mappingXml) {
		this.mappingXml = mappingXml;
	}
}
